/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = sqlserver_tokenless.c                                         */
/*  NOTE      = TDS tokenless解析                                             */
/*  DATE      = 2014/09/30 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <string.h>

#include "sqlserver_core.h"
#include "sqlserver_common.h"
#include "sqlserver_token.h"

extern void *g_p_apm_context;

#define MSSQL_RPC     0
#define MSSQL_SQL     1

/*******************************************************************************
*  FUNC     :  上报响应结果信息
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(MSSQL私有信息)
            :  p_st_hash_report((Frhash_header *))
            :  i_sql_rpc(MSSQL_RPC/MSSQL_SQL)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __sqlserver_report_data(Conntrack *p_st_conn
                                   , L7session_sqlserver_private *p_st_private
                                   , Frhash_header *p_st_hash_report
                                   , int i_sql_rpc)
{
    int i_ret = FR_SUCC;
    Frreport_body_data *p_st_report_body = NULL;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7_resp_sqlserver *p_st_resp = p_st_private->p_st_resp;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Sql_resultset *p_st_resultset = p_st_req->p_st_resultset;
    Sql_statement *p_st_statement = p_st_req->p_st_statement;

    /* 更新response结果 */
    if (i_sql_rpc == MSSQL_RPC)
    {
        i_ret = frdb_set_resultset_resp2(p_st_resultset
                                        , p_st_fragment->ui_total_len
                                        , p_st_resp->ui_rpc_effect_count
                                        , p_st_resp->arr_rpc_effect_rows
                                        , &(p_st_fragment->st_first_timestamp)
                                        , &(p_st_fragment->st_end_timestamp));
    }
    else
    {
        i_ret = frdb_set_resultset_resp2(p_st_resultset
                                        , p_st_fragment->ui_total_len
                                        , p_st_resp->ui_sql_effect_count
                                        , p_st_resp->arr_sql_effect_rows
                                        , &(p_st_fragment->st_first_timestamp)
                                        , &(p_st_fragment->st_end_timestamp));
    }

    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_set_resultset_resp2 failed!\n");
        /* 销毁request和response数据 */
        sqlserver_destroy_request(&p_st_private->p_st_req);
        sqlserver_destroy_response(&p_st_private->p_st_resp);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 创建report body */
    p_st_report_body = sqlserver_new_report_body(p_st_conn, p_st_private->p_st_sess);
    /* 创建report body失败时，不释放做成的request */
    if (p_st_report_body == NULL)
    {
        frdbg("sqlserver_new_report_body failed!\n");
        /* 销毁request和response数据 */
        sqlserver_destroy_request(&p_st_private->p_st_req);
        sqlserver_destroy_response(&p_st_private->p_st_resp);
        return APM_L7_ANALYZE_FAIL;
    }

    /* 上报request数据 */
    i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report, p_st_statement
                             , p_st_resultset, p_st_resp->l_error_num
                             , p_st_resp->p_error_msg
                             , p_st_resp->p_error_msg, &p_st_report_body);
    /* 销毁request和response数据 */
    sqlserver_destroy_request(&p_st_private->p_st_req);
    sqlserver_destroy_response(&p_st_private->p_st_resp);
    /* 上报request数据失败时，不释放做成的request */
    if (i_ret != FR_SUCC)
    {
        frdbg("frdb_report_resp2 failed!\n");
        frreport_body_free(&p_st_report_body);
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
}

/*******************************************************************************
*  FUNC     :  解析LOGIN7数据
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_private(MSSQL私有信息)
            :  p_st_hash_report((Frhash_header *))
*           :  i_whole_flg(是否完整flag)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int sqlserver_parse_response(Conntrack *p_st_conn
                            , L7session_sqlserver_private *p_st_private
                            , Frhash_header *p_st_hash_report
                            , int i_whole_flg)
{
    /* 之前没有接到request请求，则忽视该响应 */
    if (p_st_private->p_st_req == NULL)
    {
        frdbg("There no request before response!\n");
        return APM_L7_ANALYZE_SUCC;
    }

    int i_ret = FR_SUCC;
    L7_req_sqlserver *p_st_req = p_st_private->p_st_req;
    L7_resp_sqlserver *p_st_resp = NULL;
    Mssql_cursor *p_st_cursor = NULL;
    Frlist_header st_cursor_colmetadata;
    memset(&st_cursor_colmetadata, 0x0, sizeof(Frhash_header));
    uint8_t u8_first_char = 0;
    L7session_sqlserver *p_st_sess = p_st_private->p_st_sess;
    int i_tds_ver = p_st_sess->i_ser_tds_ver;
    int i_tds_min_ver = p_st_sess->i_ser_tds_min_ver;
    int i_tds_max_ver = p_st_sess->i_ser_tds_max_ver;
    int i_normal_flg = FR_YES;
    int i_try_again_flg = FR_NO;
    long l_prepare_id = 0;
    long l_cursor_id = 0;
    uint8_t u8_token_type = 0;
    unsigned long long ull_effect_rows = 0;
    unsigned long long ull_uid = 0;
    Sql_resultset *p_st_resultset = NULL;
    Sql_statement *p_st_statement = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    L7_fragment_sqlserver *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    Frreport_data *p_st_report_data=NULL;
    char arr_info[128] = {0};

    p_st_private->p_st_req->u8_packet_type = MSSQL_TDS_RESPONSE;
    /* 创建response */
    if (p_st_private->p_st_resp == NULL)
    {
        p_st_private->p_st_resp = (L7_resp_sqlserver *)frmalloc(sizeof(L7_resp_sqlserver));
        if (p_st_private->p_st_resp == NULL)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 初始化response */
        memset(p_st_private->p_st_resp, 0x0, sizeof(L7_resp_sqlserver));
        p_st_private->p_st_resp->i_ser_tds_ver_tmp = i_tds_ver;
        p_st_private->p_st_resp->i_ser_tds_min_ver_tmp = i_tds_min_ver;
        p_st_private->p_st_resp->i_ser_tds_max_ver_tmp = i_tds_max_ver;
    }
    p_st_resp = p_st_private->p_st_resp;
    /* 取得statement和resultset索引 */
    p_st_statement = p_st_req->p_st_statement;
    p_st_resultset = p_st_req->p_st_resultset;

    /* pre login只有单独的一个prelogin token,且不同的TDS版本都是一样的 */
    if (p_st_fragment->ui_parsed_index == 0)
    {
        bytebuff_peek_char(p_st_data, &u8_first_char);
        if (u8_first_char == MSSQL_TDS_PRELOGIN_TOKEN)
        {
            bytebuff_skip(p_st_data, 1);
            i_ret = sqlserver_parse_prelogin(p_st_conn , p_st_private, p_st_hash_report
                                             , i_whole_flg, MSSQL_SRV2CLI);
            if (i_ret == APM_L7_ANALYZE_FAIL)
            {
                frdbg("Parse prelogin failed!\n");
            }
            /* 因为pre login不用上报，销毁当前响应的请求信息 */
            sqlserver_destroy_request(&p_st_private->p_st_req);
            p_st_private->p_st_req = NULL;
            frfree(p_st_private->p_st_resp);
            p_st_private->p_st_resp = NULL;
            return i_ret;
        }
    }

    /* 当request是游标fetch时，对应的COLMETADATA结构需要从cursor中取得 */
    if (p_st_req->u8_request_type == MSSQL_TDS_RPCREQUEST
        && p_st_req->u16_rpc_type == MSSQL_PREPARE_CURSOR_FETCH
        && p_st_statement != NULL)
    {
        st_cursor_colmetadata = p_st_statement->st_metadata_column;
    }

    bytebuff_setPosition(p_st_data, p_st_fragment->ui_parsed_index);
    /* 有请求时，取得对应的响应结果 */
    while (bytebuff_remaining(p_st_data))
    {
        /* 取得token，并且跳过token */
        bytebuff_get_char(p_st_data, &u8_token_type);

        /* 解析token */
        switch (u8_token_type)
        {
            case MSSQL_TDS_ALTMETADATA_TOKEN:
                /*
                * ALTMETADATA和ALTROW是一一对应关系，
                * 假如出现第二个ALTMETADATA,释放之前的(实际情况不会出现)
                */
                frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                                 , sqlserver_altmetadata_node_free);
                i_ret = sqlserver_altmetadata_token(p_st_data, i_whole_flg
                                                   , &p_st_resp->i_ser_tds_ver_tmp
                                                   , &p_st_resp->i_ser_tds_min_ver_tmp
                                                   , &p_st_resp->i_ser_tds_max_ver_tmp
                                                   , &i_try_again_flg
                                                   , &p_st_resp->st_altmetadata_header);
                break;

            case MSSQL_TDS_ALTROW_TOKEN:
                i_ret = sqlserver_altrow_token(p_st_data, i_whole_flg
                                              , &p_st_resp->st_altmetadata_header);
                break;

            case MSSQL_TDS_COLMETADATA_TOKEN:
                /*
                * COLMETADATA和ROW或者NBCROW是一一对应关系，
                * 假如出现第二个COLMETADATA,释放之前的(实际情况不会出现)
                */
                frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                                  , frdb_metadata_node_free);
                i_ret = sqlserver_colmetadata_token(p_st_data, i_whole_flg
                                                   , &p_st_resp->i_ser_tds_ver_tmp
                                                   , &p_st_resp->i_ser_tds_min_ver_tmp
                                                   , &p_st_resp->i_ser_tds_max_ver_tmp
                                                   , &i_try_again_flg
                                                   , &p_st_resp->st_colmetadata_header);
                break;

            case MSSQL_TDS_COLINFO_TOKEN:
                i_ret = sqlserver_colinfo_token(p_st_data, i_whole_flg);
                break;

            case MSSQL_TDS_DONE_TOKEN:
                i_ret = sqlserver_done_token(p_st_data, i_whole_flg
                                            , &p_st_resp->i_ser_tds_ver_tmp
                                            , &p_st_resp->i_ser_tds_min_ver_tmp
                                            , &p_st_resp->i_ser_tds_max_ver_tmp
                                            , &i_try_again_flg
                                            , &i_normal_flg
                                            , &ull_effect_rows);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    break;
                }
                if (p_st_resp->ui_sql_effect_count < sizeof(p_st_resp->arr_sql_effect_rows))
                {
                    p_st_resp->arr_sql_effect_rows[p_st_resp->ui_sql_effect_count++] = ull_effect_rows;
                }
                break;

            case MSSQL_TDS_DONEPROC_TOKEN:
                i_ret = sqlserver_doneproc_token(p_st_data, i_whole_flg
                                                , &p_st_resp->i_ser_tds_ver_tmp
                                                , &p_st_resp->i_ser_tds_min_ver_tmp
                                                , &p_st_resp->i_ser_tds_max_ver_tmp
                                                , &i_try_again_flg
                                                , &i_normal_flg
                                                , &ull_effect_rows);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    break;
                }
                if (p_st_resp->ui_sql_effect_count < sizeof(p_st_resp->arr_sql_effect_rows))
                {
                    p_st_resp->arr_sql_effect_rows[p_st_resp->ui_sql_effect_count++] = ull_effect_rows;
                }
                break;

            case MSSQL_TDS_DONEINPROC_TOKEN:
                i_ret = sqlserver_doneinproc_token(p_st_data, i_whole_flg
                                                  , &p_st_resp->i_ser_tds_ver_tmp
                                                  , &p_st_resp->i_ser_tds_min_ver_tmp
                                                  , &p_st_resp->i_ser_tds_max_ver_tmp
                                                  , &i_try_again_flg
                                                  , &ull_effect_rows);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    break;
                }
                if (p_st_resp->ui_rpc_effect_count < sizeof(p_st_resp->arr_rpc_effect_rows))
                {
                    p_st_resp->arr_rpc_effect_rows[p_st_resp->ui_rpc_effect_count++] = ull_effect_rows;
                }
                break;

            case MSSQL_TDS_ENVCHANGE_TOKEN:
                i_ret = sqlserver_envchange_token(p_st_data, i_whole_flg
                                                 , &p_st_resp->i_ser_tds_ver_tmp
                                                 , &p_st_resp->i_ser_tds_min_ver_tmp
                                                 , &p_st_resp->i_ser_tds_max_ver_tmp
                                                 , &p_st_resp->p_charset);
                break;

            case MSSQL_TDS_ERROR_TOKEN:
                i_ret = sqlserver_error_token(p_st_data, i_whole_flg
                                             , &p_st_resp->i_ser_tds_ver_tmp
                                             , &p_st_resp->i_ser_tds_min_ver_tmp
                                             , &p_st_resp->i_ser_tds_max_ver_tmp
                                             , &p_st_resp->l_error_num
                                             , &p_st_resp->p_error_msg);
                break;

            case MSSQL_TDS_FEATUREEXTACK_TOKEN:  /* (introduced in TDS 7.4) */
                i_ret = sqlserver_featureextack_token(p_st_data, i_whole_flg);
                break;

            case MSSQL_TDS_INFO_TOKEN:
                i_ret = sqlserver_info_token(p_st_data, i_whole_flg
                                            , &p_st_resp->i_ser_tds_ver_tmp
                                            , &p_st_resp->i_ser_tds_min_ver_tmp
                                            , &p_st_resp->i_ser_tds_max_ver_tmp);
                break;

            case MSSQL_TDS_LOGINACK_TOKEN:
                i_ret = sqlserver_loginack_token(p_st_data, i_whole_flg, &i_tds_ver);
                break;

            case MSSQL_TDS_NBCROW_TOKEN:         /* (introduced in TDS 7.3) */
                i_ret = sqlserver_nbcrow_token(p_st_data, i_whole_flg
                                              , &p_st_resp->i_ser_tds_ver_tmp
                                              , &p_st_resp->i_ser_tds_min_ver_tmp
                                              , &p_st_resp->i_ser_tds_max_ver_tmp
                                              , &p_st_resp->st_colmetadata_header);
                break;

            case MSSQL_TDS_OFFSET_TOKEN:
                i_ret = sqlserver_offset_token(p_st_data, i_whole_flg
                                              , &p_st_resp->i_ser_tds_ver_tmp
                                              , &p_st_resp->i_ser_tds_min_ver_tmp
                                              , &p_st_resp->i_ser_tds_max_ver_tmp);
                break;

            case MSSQL_TDS_ORDER_TOKEN:
                i_ret = sqlserver_order_token(p_st_data, i_whole_flg);
                break;

            case MSSQL_TDS_RETURNSTATUS_TOKEN:
                i_ret = sqlserver_returnstatus_token(p_st_data, i_whole_flg);
                break;

            case MSSQL_TDS_RETURNVALUE_TOKEN:
                i_ret = sqlserver_returnvalue_token(p_st_data, i_whole_flg
                                                   , &p_st_resp->i_ser_tds_ver_tmp
                                                   , &p_st_resp->i_ser_tds_min_ver_tmp
                                                   , &p_st_resp->i_ser_tds_max_ver_tmp
                                                   , &i_try_again_flg
                                                   , &ull_uid);
                if (p_st_resp->ui_return_value_count < sizeof(p_st_resp->arr_return_values))
                {
                    p_st_resp->arr_return_values[p_st_resp->ui_return_value_count++] = ull_uid;
                }
                break;

            case MSSQL_TDS_ROW_TOKEN:
                /* 当request是游标fetch时，对应的colmetadata结构是从cursor execute中得到的  */
                if (p_st_req->u8_request_type == MSSQL_TDS_RPCREQUEST
                    && p_st_req->u16_rpc_type == MSSQL_PREPARE_CURSOR_FETCH
                    && frlist_size(&p_st_resp->st_colmetadata_header) == 0)
                {
                    i_ret = sqlserver_row_token(p_st_data, i_whole_flg
                                               , &st_cursor_colmetadata);
                }
                else
                {
                    i_ret = sqlserver_row_token(p_st_data, i_whole_flg
                                               , &p_st_resp->st_colmetadata_header);
                }
                break;

            case MSSQL_TDS_SESSIONSTATE_TOKEN:   /* (introduced in TDS 7.4) */
                i_ret = sqlserver_sessionstate_token(p_st_data, i_whole_flg);
                break;

            case MSSQL_TDS_SSPI_TOKEN:
                i_ret = sqlserver_sspi_token(p_st_data, i_whole_flg);
                break;

            case MSSQL_TDS_TABNAME_TOKEN:
                i_ret = sqlserver_tabname_token(p_st_data, i_whole_flg
                                               , &p_st_resp->i_ser_tds_ver_tmp
                                               , &p_st_resp->i_ser_tds_min_ver_tmp
                                               , &p_st_resp->i_ser_tds_max_ver_tmp);
                break;

            default:
                /* 之前用低版本解析过，可能是低版本接卸导致的错误, 低版本+1再解析 */
                if (i_try_again_flg == FR_YES)
                {
                    /* 全部初始化 */
                    p_st_resp->i_ser_tds_ver_tmp = i_tds_ver;
                    p_st_resp->i_ser_tds_min_ver_tmp = ++i_tds_min_ver;
                    p_st_resp->i_ser_tds_max_ver_tmp = i_tds_max_ver;
                    if (p_st_resp->i_ser_tds_min_ver_tmp == p_st_resp->i_ser_tds_max_ver_tmp)
                    {
                        p_st_resp->i_ser_tds_ver_tmp = p_st_resp->i_ser_tds_min_ver_tmp;
                    }
                    i_try_again_flg = FR_NO;
                    p_st_resp->l_error_num = 0;
                    ull_effect_rows = 0;
                    p_st_resp->ui_rpc_effect_count = 0;
                    p_st_resp->ui_sql_effect_count = 0;
                    p_st_resp->ui_return_value_count = 0;
                    bytebuff_rewind(p_st_data);
                    sqlserver_free((void **)&p_st_resp->p_charset);
                    sqlserver_free((void **)&p_st_resp->p_error_msg);
                    frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                                     , sqlserver_altmetadata_node_free);
                    frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                                     , frdb_metadata_node_free);
                    bytebuff_setPosition(p_st_data, 0);
                    continue;
                }

                frdbg("Unknown defined token[%02X]!\n", u8_token_type);
                sqlserver_free((void **)&p_st_resp->p_charset);
                sqlserver_free((void **)&p_st_resp->p_error_msg);
                frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                                 , sqlserver_altmetadata_node_free);
                frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                                 , frdb_metadata_node_free);
                sqlserver_destroy_request(&p_st_private->p_st_req);
                frfree(p_st_private->p_st_resp);
                p_st_private->p_st_resp = NULL;
                return APM_L7_ANALYZE_FAIL;
        }

        if (i_ret == APM_L7_ANALYZE_FAIL)
        {
            /* 之前用低版本解析过，可能是低版本接卸导致的错误，低版本+1再解析 */
            if (i_try_again_flg == FR_YES)
            {
                /* 全部初始化 */
                p_st_resp->i_ser_tds_ver_tmp = i_tds_ver;
                p_st_resp->i_ser_tds_min_ver_tmp = ++i_tds_min_ver;
                p_st_resp->i_ser_tds_max_ver_tmp = i_tds_max_ver;
                if (p_st_resp->i_ser_tds_min_ver_tmp == p_st_resp->i_ser_tds_max_ver_tmp)
                {
                    p_st_resp->i_ser_tds_ver_tmp = p_st_resp->i_ser_tds_min_ver_tmp;
                }
                i_try_again_flg = FR_NO;
                p_st_resp->l_error_num = 0;
                ull_effect_rows = 0;
                p_st_resp->ui_rpc_effect_count = 0;
                p_st_resp->ui_sql_effect_count = 0;
                p_st_resp->ui_return_value_count = 0;
                bytebuff_rewind(p_st_data);
                sqlserver_free((void **)&p_st_resp->p_charset);
                sqlserver_free((void **)&p_st_resp->p_error_msg);
                frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                                 , sqlserver_altmetadata_node_free);
                frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                                 , frdb_metadata_node_free);
                bytebuff_setPosition(p_st_data, 0);
                continue;
            }

            frdbg("Parse [%02X] token failed!\n", u8_token_type);
            sqlserver_free((void **)&p_st_resp->p_charset);
            sqlserver_free((void **)&p_st_resp->p_error_msg);
            frlist_remove_all(&(p_st_resp->st_altmetadata_header)
                             , sqlserver_altmetadata_node_free);
            frlist_remove_all(&(p_st_resp->st_colmetadata_header)
                             , frdb_metadata_node_free);
            sqlserver_destroy_request(&p_st_private->p_st_req);
            frfree(p_st_private->p_st_resp);
            p_st_private->p_st_resp = NULL;
            return APM_L7_ANALYZE_FAIL;
        }
        else if (i_ret == APM_L7_ANALYZE_TODO)
        {
            return APM_L7_ANALYZE_TODO;
        }
        else
        {
            p_st_fragment->ui_parsed_index = bytebuff_getPosition(p_st_data);
        }
    }

    if (i_whole_flg != FR_YES)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 设置版本 */
    p_st_sess->i_ser_tds_ver = p_st_resp->i_ser_tds_ver_tmp;
    p_st_sess->i_ser_tds_min_ver = p_st_resp->i_ser_tds_min_ver_tmp;
    p_st_sess->i_ser_tds_max_ver = p_st_resp->i_ser_tds_max_ver_tmp;
    /* 设置charset */
    if (p_st_resp->p_charset)
    {
        sqlserver_free((void **)&(p_st_sess->p_tds_charset));
        p_st_sess->p_tds_charset = p_st_resp->p_charset;
        p_st_resp->p_charset = NULL;
    }

    /* 根据请求类型做相应的操作 */
    switch (p_st_req->u8_request_type)
    {
        /* request类型是PRETDS7LOGIN，BULKLOADBCP，TRANSMGRREQ，SSPIMESSAGE，PRELOGIN不用上报 */
        case MSSQL_TDS_PRETDS7LOGIN:
        case MSSQL_TDS_BULKLOADBCP:
        case MSSQL_TDS_TRANSMGRREQ:
        case MSSQL_TDS_SSPIMESSAGE:
        case MSSQL_TDS_PRELOGIN:
        case MSSQL_TDS_ATTENTION:
            /* 销毁request和response数据 */
            frdbg("Parse [%2X]response success!\n", p_st_req->u8_request_type);
            sqlserver_destroy_request(&p_st_private->p_st_req);
            sqlserver_destroy_response(&p_st_private->p_st_resp);
            return APM_L7_ANALYZE_SUCC;

        /* LOGIN信息 */
        case MSSQL_TDS_LOGIN7:
            if (p_st_sess->p_db_user)
            {
                snprintf(arr_info, sizeof(arr_info), "%s login", p_st_sess->p_db_user);
            }
            else
            {
                snprintf(arr_info, sizeof(arr_info), "login");
            }
            if (i_normal_flg == FR_NO)
            {
                p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON_REJECT, arr_info, &p_st_fragment->st_first_timestamp);
            }
            else
            {
                p_st_sess->st_login = p_st_fragment->st_first_timestamp;
                p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON, arr_info, &p_st_fragment->st_first_timestamp);
            }
            if (p_st_report_data)
            {
                i_ret = frreport_send(g_p_apm_context, &p_st_report_data);
                if (i_ret != FR_SUCC)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            /* 销毁request/response数据 */
            sqlserver_destroy_request(&p_st_private->p_st_req);
            sqlserver_destroy_response(&p_st_private->p_st_resp);
            //frdbg("Parse LOGIN7 response success!\n");
            return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

        /* request类型SQLBATCH直接上报 */
        case MSSQL_TDS_SQLBATCH:
            i_ret = __sqlserver_report_data(p_st_conn
                                           , p_st_private
                                           , p_st_hash_report
                                           , MSSQL_SQL);
            //frdbg("Parse SQLBATCH response!\n");
            return i_ret;

        /* RPC信息 */
        case MSSQL_TDS_RPCREQUEST:
            switch (p_st_req->u16_rpc_type)
            {
                /*
                * 如果是远程过程调用或者存储过程或者prepare execute, 直接上报,
                * 上报完了之后再释放request和response信息
                */
                case MSSQL_PREPARE_RPC_NAME:
                    /* 上报结果 */
                    i_ret = __sqlserver_report_data(p_st_conn
                                                   , p_st_private
                                                   , p_st_hash_report
                                                   , MSSQL_RPC);
                    //frdbg("Parse rpc name response success!\n");
                    return i_ret;

                case MSSQL_PREPARE_PREPEXEC:
                    /* prepare出错直接上报 */
                    if (i_normal_flg == FR_NO)
                    {
                        frdbg("Prepare:[PREPEXEC] response failed!\n");
                        /* 上报结果 */
                        i_ret = __sqlserver_report_data(p_st_conn
                                                       , p_st_private
                                                       , p_st_hash_report
                                                       , MSSQL_RPC);
                        return i_ret;
                    }

                    /* 更新response结果 */
                    i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                    , p_st_fragment->ui_total_len
                                                    , p_st_resp->ui_rpc_effect_count
                                                    , p_st_resp->arr_rpc_effect_rows
                                                    , &(p_st_fragment->st_first_timestamp)
                                                    , &(p_st_fragment->st_end_timestamp));
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_set_resultset_resp2 failed!\n");
                        /* 销毁request和response数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        sqlserver_destroy_response(&p_st_private->p_st_resp);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 取得prepare ID */
                    l_prepare_id = (long)p_st_resp->arr_return_values[0];
                    /* 销毁response数据 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    /* 删除可能存在于cursor list中的数据 */
                    sqlserver_del_specified_cursor2(&(p_st_private->list_cursor)
                                                   , l_prepare_id);
                    /* 追加到prepare hash */
                    i_ret = frdb_add_statement(p_st_private->p_hash_prepare
                                               , l_prepare_id, p_st_statement);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_add_statement failed!\n");
                        /* 销毁request数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    p_st_req->p_st_statement = NULL;
                    /* 创建report body */
                    p_st_report_body = sqlserver_new_report_body(p_st_conn
                                                                , p_st_sess);
                    /* 创建report body失败时，不释放做成的request */
                    if (p_st_report_body == NULL)
                    {
                        frdbg("sqlserver_new_report_body failed!\n");
                        frdb_init_resultset(p_st_resultset
                                           , frct_seq_increase(p_st_conn));
                        frdb_statement_used(p_st_statement);
                        /* 销毁request数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 上报request数据 */
                    i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report
                                             , p_st_statement, p_st_resultset
                                             , 0, NULL, NULL, &p_st_report_body);
                    /* 销毁request和response数据 */
                    frdb_init_resultset(p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    frdb_statement_used(p_st_statement);
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    /* 上报request数据失败时，不释放做成的request */
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_report_resp2 failed!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }

                    frdb_init_resultset(p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    frdb_statement_used(p_st_statement);
                    //frdbg("Parse PREPEXEC response success!\n");
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                /*
                * 如果是prepare sql则需要将响应的数据存储到hash中,
                * 供以后的prepare execute使用
                */
                case MSSQL_PREPARE_PREPARE:
                case MSSQL_PREPARE_CURSOR_PREPARE:
                case MSSQL_PREPARE_CURSOR_OPEN:
                    /* prepare出错直接上报 */
                    if (i_normal_flg == FR_NO)
                    {
                        frdbg("Prepare:[%2X] response failed!\n", p_st_req->u16_rpc_type);
                        /* 上报结果 */
                        i_ret = __sqlserver_report_data(p_st_conn
                                                       , p_st_private
                                                       , p_st_hash_report
                                                       , MSSQL_RPC);
                        return i_ret;
                    }

                    /* 更新response结果 */
                    i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                    , p_st_fragment->ui_total_len
                                                    , 0
                                                    , NULL
                                                    , &(p_st_fragment->st_first_timestamp)
                                                    , &(p_st_fragment->st_end_timestamp));

                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_set_resultset_resp2 failed!\n");
                        /* 销毁request和response数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        sqlserver_destroy_response(&p_st_private->p_st_resp);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 取得prepare ID */
                    l_prepare_id = (long)p_st_resp->arr_return_values[0];
                    if (p_st_req->u16_rpc_type == MSSQL_PREPARE_CURSOR_PREPARE
                        || p_st_req->u16_rpc_type == MSSQL_PREPARE_CURSOR_OPEN)
                    {
                    	p_st_statement->st_metadata_column = p_st_resp->st_colmetadata_header;
                    	memset(&p_st_resp->st_colmetadata_header, 0x0, sizeof(Frlist_header));
                    }
                    /* 销毁response数据 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    /* 删除可能存在于cursor list中的数据 */
                    sqlserver_del_specified_cursor2(&(p_st_private->list_cursor)
                                                   , l_prepare_id);
                    /* 追加到prepare hash */
                    i_ret = frdb_add_statement(p_st_private->p_hash_prepare
                                               , l_prepare_id, p_st_statement);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_add_statement failed!\n");
                        /* 销毁request数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 销毁request和response数据 */
                    p_st_req->p_st_statement = NULL;
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    //frdbg("parse prepare response success!\n");
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                case MSSQL_PREPARE_CURSOR_PREPEXEC:
                    /* prepare出错直接上报 */
                    if (i_normal_flg == FR_NO)
                    {
                        frdbg("Prepare CURSOR_PREPEXEC response failed!\n");
                        /* 上报结果 */
                        i_ret = __sqlserver_report_data(p_st_conn
                                                       , p_st_private
                                                       , p_st_hash_report
                                                       , MSSQL_RPC);
                        return i_ret;
                    }

                    /* 不是select直接上报 */
                    if (sqlserver_select_chk(p_st_statement->p_sql) == FR_NO)
                    {
                        /* 更新response结果 */
                        i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                        , p_st_fragment->ui_total_len
                                                        , p_st_resp->ui_rpc_effect_count
                                                        , p_st_resp->arr_rpc_effect_rows
                                                        , &(p_st_fragment->st_first_timestamp)
                                                        , &(p_st_fragment->st_end_timestamp));
                        if (i_ret != FR_SUCC)
                        {
                            frdbg("frdb_set_resultset_resp2 failed!\n");
                            /* 销毁request和response数据 */
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }

                        /* 创建report body */
                        p_st_report_body = sqlserver_new_report_body(p_st_conn
                                                                    , p_st_sess);
                        /* 创建report body失败时，不释放做成的request */
                        if (p_st_report_body == NULL)
                        {
                            frdbg("sqlserver_new_report_body failed!\n");
                            //p_st_req->p_st_statement = NULL;
                            //frdb_init_resultset(p_st_resultset
                            //                   , frct_seq_increase(p_st_conn));
                            //frdb_statement_used(p_st_statement);
                            /* 销毁request和response数据 */
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }

                        /* 上报request数据 */
                        i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report
                                                 , p_st_statement, p_st_resultset
                                                 , 0, NULL, NULL, &p_st_report_body);
                        /* 上报request数据失败时，不释放做成的request */
                        if (i_ret != FR_SUCC)
                        {
                            frdbg("frdb_report_resp2 failed!\n");
                            /* 销毁request和response数据 */
                            //p_st_req->p_st_statement = NULL;
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }
                        frdb_init_resultset(p_st_resultset
                                           , frct_seq_increase(p_st_conn));
                        frdb_statement_used(p_st_statement);
                    }
                    else
                    {
                        /* 更新response结果 */
                        i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                        , p_st_fragment->ui_total_len
                                                        , 0
                                                        , NULL
                                                        , &(p_st_fragment->st_first_timestamp)
                                                        , &(p_st_fragment->st_end_timestamp));

                        if (i_ret != FR_SUCC)
                        {
                            frdbg("frdb_set_resultset_resp2 failed!\n");
                            /* 销毁request和response数据 */
                            frdb_del_last_resultset(p_st_statement);
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }
                    }

                    /* 取得prepare ID和cursor ID */
                    l_prepare_id = (long)p_st_resp->arr_return_values[0];
                    l_cursor_id = (long)p_st_resp->arr_return_values[1];
                	p_st_statement->st_metadata_column = p_st_resp->st_colmetadata_header;
                	memset(&p_st_resp->st_colmetadata_header, 0x0, sizeof(Frlist_header));
                    /* 销毁response数据 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    /* 做成cursor信息 */
                    p_st_cursor = (Mssql_cursor *)frmalloc(sizeof(Mssql_cursor));
                    if (p_st_cursor == NULL)
                    {
                        frdbg("frmalloc failed!\n");
                        /* 销毁request数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }
                    memset(p_st_cursor, 0x0, sizeof(Mssql_cursor));
                    p_st_resultset->l_id = l_cursor_id;
                    p_st_cursor->l_cursor_id = l_cursor_id;
                    p_st_cursor->l_prepare_id = l_prepare_id;
                    /* 设置statement和resultset索引 */
                    p_st_cursor->p_st_statement = p_st_statement;
                    p_st_cursor->p_st_resultset = p_st_resultset;
                    /* 追加到cursor */
                    i_ret = sqlserver_data_push(&(p_st_private->list_cursor)
                                               , p_st_cursor);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("sqlserver_data_push failed!\n");
                        /* 销毁request数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);;
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 删除可能存在于cursor list中的数据 */
                    sqlserver_del_specified_cursor2(&(p_st_private->list_cursor)
                                                   , l_prepare_id);
                    /* 追加到prepare hash */
                    i_ret = frdb_add_statement(p_st_private->p_hash_prepare
                                               , l_prepare_id, p_st_statement);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_add_statement failed!\n");
                        /* 销毁request数据 */
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 销毁request和response数据 */
                    p_st_req->p_st_statement = NULL;
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    //frdbg("parse prepare response success!\n");
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                case MSSQL_PREPARE_EXECUTE:
                    /* 上包结果集 */
                    i_ret = __sqlserver_report_data(p_st_conn
                                                   , p_st_private
                                                   , p_st_hash_report
                                                   , MSSQL_RPC);
                    frdb_init_resultset(p_st_resultset
                                       , frct_seq_increase(p_st_conn));
                    frdb_statement_used(p_st_statement);
                    return i_ret;

                case MSSQL_PREPARE_CURSOR_EXECUTE:
                    /* prepare出错直接上报 */
                    if (i_normal_flg == FR_NO)
                    {
                        frdbg("Prepare CURSOR_EXECUTE response failed!\n");
                        /* 上包结果集 */
                        i_ret = __sqlserver_report_data(p_st_conn
                                                       , p_st_private
                                                       , p_st_hash_report
                                                       , MSSQL_RPC);
                        frdb_del_last_resultset(p_st_statement);
                        return i_ret;
                    }

                    /* 不是select直接上报 */
                    if (sqlserver_select_chk(p_st_statement->p_sql) == FR_NO)
                    {
                        /* 更新response结果 */
                        i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                        , p_st_fragment->ui_total_len
                                                        , p_st_resp->ui_rpc_effect_count
                                                        , p_st_resp->arr_rpc_effect_rows
                                                        , &(p_st_fragment->st_first_timestamp)
                                                        , &(p_st_fragment->st_end_timestamp));
                        if (i_ret != FR_SUCC)
                        {
                            frdbg("frdb_set_resultset_resp2 failed!\n");
                            frdb_del_last_resultset(p_st_statement);
                            /* 销毁request和response数据 */
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }

                        /* 创建report body */
                        p_st_report_body = sqlserver_new_report_body(p_st_conn
                                                                    , p_st_sess);
                        /* 创建report body失败时，不释放做成的request */
                        if (p_st_report_body == NULL)
                        {
                            frdbg("sqlserver_new_report_body failed!\n");
                            //frdb_init_resultset(p_st_resultset
                            //                   , frct_seq_increase(p_st_conn));
                            //frdb_statement_used(p_st_statement);
                            /* 销毁request和response数据 */
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }

                        /* 上报request数据 */
                        i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report
                                                 , p_st_statement, p_st_resultset
                                                 , 0, NULL, NULL, &p_st_report_body);
                        /* 上报request数据失败时，不释放做成的request */
                        if (i_ret != FR_SUCC)
                        {
                            frdbg("frdb_report_resp2 failed!\n");
                            /* 销毁request和response数据 */
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }
                        frdb_init_resultset(p_st_resultset
                                           , frct_seq_increase(p_st_conn));
                        frdb_statement_used(p_st_statement);
                    }
                    else
                    {
                        /* 更新response结果 */
                        i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                        , p_st_fragment->ui_total_len
                                                        , 0
                                                        , NULL
                                                        , &(p_st_fragment->st_first_timestamp)
                                                        , &(p_st_fragment->st_end_timestamp));
                        if (i_ret != FR_SUCC)
                        {
                            frdbg("frdb_set_resultset_resp2 failed!\n");
                            frdb_del_last_resultset(p_st_statement);
                            /* 销毁request和response数据 */
                            sqlserver_destroy_request(&p_st_private->p_st_req);
                            sqlserver_destroy_response(&p_st_private->p_st_resp);
                            return APM_L7_ANALYZE_FAIL;
                        }
                    }

                    /* 取得cursor ID */
                    l_cursor_id = (long)p_st_resp->arr_return_values[0];
                    p_st_resultset->l_id = l_cursor_id;

                    /* 销毁response和request数据 */
                    p_st_private->p_st_req->p_st_statement = NULL;
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    /* 做成cursor信息 */
                    p_st_cursor = (Mssql_cursor *)frmalloc(sizeof(Mssql_cursor));
                    if (p_st_cursor == NULL)
                    {
                        frdbg("frmalloc failed!\n");
                        frdb_del_last_resultset(p_st_statement);
                        /* 销毁request数据 */
                        return APM_L7_ANALYZE_FAIL;
                    }
                    memset(p_st_cursor, 0x0, sizeof(Mssql_cursor));
                    p_st_cursor->l_cursor_id = l_cursor_id;
                    p_st_cursor->l_prepare_id = p_st_statement->l_cursor_id;
                    /* 设置statement和resultset索引 */
                    p_st_cursor->p_st_statement = p_st_statement;
                    p_st_cursor->p_st_resultset = p_st_resultset;

                    /* 追加到cursor */
                    i_ret = sqlserver_data_push(&(p_st_private->list_cursor)
                                               , p_st_cursor);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("sqlserver_data_push failed!\n");
                        frdb_del_last_resultset(p_st_statement);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    //frdbg("Parse rpc cursor exec response success!\n");
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                case MSSQL_PREPARE_CURSOR_FETCH:
                    /* prepare出错直接上报 */
                    if (i_normal_flg == FR_NO)
                    {
                        frdbg("Prepare CURSOR FETCH response failed!\n");
                        /* 上包结果集 */
                        i_ret = __sqlserver_report_data(p_st_conn
                                                       , p_st_private
                                                       , p_st_hash_report
                                                       , MSSQL_RPC);
                        frdb_init_resultset(p_st_resultset
                                           , frct_seq_increase(p_st_conn));
                        frdb_statement_used(p_st_statement);
                        return i_ret;
                    }

                    /* 实际上只是做response长度已经影响行数的更新 */
                    i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                    , p_st_fragment->ui_total_len
                                                    , p_st_resp->ui_rpc_effect_count
                                                    , p_st_resp->arr_rpc_effect_rows
                                                    , &(p_st_fragment->st_first_timestamp)
                                                    , &(p_st_fragment->st_end_timestamp));
                    /* 销毁response数据 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_set_resultset_resp2 failed!\n");
                        frdb_init_resultset(p_st_resultset
                                           , frct_seq_increase(p_st_conn));
                        frdb_statement_used(p_st_statement);
                        return APM_L7_ANALYZE_FAIL;
                    }
                    //frdbg("parse rpc cursor fetch response success!\n");
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                case MSSQL_PREPARE_CURSOR_CLOSE:
                    /* 设置response code */
                    p_st_cursor = sqlserver_get_cursor_info(&(p_st_private->list_cursor), l_cursor_id);

                    /* 更新response结果 */
                    i_ret = frdb_set_resultset_resp2(p_st_resultset
                                                    , p_st_fragment->ui_total_len
                                                    , 0
                                                    , NULL
                                                    , &(p_st_fragment->st_first_timestamp)
                                                    , &(p_st_fragment->st_end_timestamp));
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_set_resultset_resp2 failed!\n");
                        sqlserver_destroy_response(&p_st_private->p_st_resp);
                        frdb_statement_used(p_st_statement);
                        if (p_st_cursor)
                        {
                            frdb_del_specified_resultset(p_st_statement
                                                        , p_st_req->l_uid);
                            sqlserver_del_specified_cursor(&(p_st_private->list_cursor)
                                                        , p_st_req->l_uid);
                        }
                        else
                        {
                            frhash2_delLong(p_st_private->p_hash_prepare
                                           , p_st_req->l_uid
                                           , frdb_statement_node_free);
                        }
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 创建report body */
                    p_st_report_body = sqlserver_new_report_body(p_st_conn
                                                                , p_st_sess);
                    /* 创建report body失败时，不释放做成的request */
                    if (p_st_report_body == NULL)
                    {
                        frdbg("frdb_response_format2 failed!\n");
                        sqlserver_destroy_response(&p_st_private->p_st_resp);
                        frdb_statement_used(p_st_statement);
                        if (p_st_cursor)
                        {
                            frdb_del_specified_resultset(p_st_statement
                                                        , p_st_req->l_uid);
                            sqlserver_del_specified_cursor(&(p_st_private->list_cursor)
                                                        , p_st_req->l_uid);
                        }
                        else
                        {
                            frhash2_delLong(p_st_private->p_hash_prepare
                                           , p_st_req->l_uid
                                           , frdb_statement_node_free);
                        }
                        sqlserver_destroy_request(&p_st_private->p_st_req);
                        return APM_L7_ANALYZE_FAIL;
                    }

                    /* 上报request数据 */
                    i_ret = frdb_report_resp2(p_st_conn, p_st_hash_report
                                             , p_st_statement, p_st_resultset
                                             , p_st_resp->l_error_num
                                             , p_st_resp->p_error_msg
                                             , p_st_resp->p_error_msg
                                             , &p_st_report_body);
                    /* 删除该游标对应信息 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    frdb_statement_used(p_st_statement);
                    if (p_st_cursor)
                    {
                        frdb_del_specified_resultset(p_st_statement
                                                    , p_st_req->l_uid);
                        sqlserver_del_specified_cursor(&(p_st_private->list_cursor)
                                                    , p_st_req->l_uid);
                    }
                    else
                    {
                        frhash2_delLong(p_st_private->p_hash_prepare
                                       , p_st_req->l_uid
                                       , frdb_statement_node_free);
                    }
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    if (i_ret != FR_SUCC)
                    {
                        frdbg("frdb_report_resp2 failed!\n");
                        return APM_L7_ANALYZE_FAIL;
                    }

                    //frdbg("Parse rpc cursor close response success!\n");
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                case MSSQL_PREPARE_CURSOR_UNPREPARE:
                case MSSQL_PREPARE_UNPREPARE:
                    frhash2_delLong(p_st_private->p_hash_prepare
                                   , p_st_req->l_uid
                                   , frdb_statement_node_free);
                    /* 销毁response和request数据 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

                /* 其他情况先不上报 todo */
                default:
                    /* 销毁response和request数据 */
                    sqlserver_destroy_response(&p_st_private->p_st_resp);
                    sqlserver_destroy_request(&p_st_private->p_st_req);
                    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
            }

        default:/* 实际不会发生 */
            /* 销毁response和request数据 */
            sqlserver_destroy_response(&p_st_private->p_st_resp);
            sqlserver_destroy_request(&p_st_private->p_st_req);
            return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }
}
